/*
 * Copyright (c) 2018-2023 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include <rpc/types.h>
#include "limit.h"

void
init_resource_limit(int rLimits[])
{
    unsigned int i;

    for (i = 0; i < RESOURCE_LIMIT_NUM; i++) {
        rLimits[i] = DEFAULT_RESOURCE_LIMIT;
    }

    return;
}

int
is_limitok(int *rLimits)
{
#define EXCEED_MAX_INT(x) ( (x) > 0 ? (unsigned int)(x) >> 21 : 0 )

    if ( EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_FSIZE])
	 || EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_DATA])
	 || EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_STACK])
	 || EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_CORE])
	 || EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_RSS])
	 || EXCEED_MAX_INT(rLimits[RESOURCE_LIMIT_SWAP]) ) {
	return 0;
    } else {
	return 1;
    }
}

static int SHIFT_32 = 32;

void
set_resource_limit(struct resourceLimit *rlimit, struct rlimit *limit, int index)
{
    int softok = FALSE;
    int hardok = FALSE;

    if (rlimit->rlim_curl == 0xffffffff && rlimit->rlim_curh == 0x7fffffff) {
	limit->rlim_cur = RLIM_INFINITY;
	softok = TRUE;
    }

    if (rlimit->rlim_maxl == 0xffffffff && rlimit->rlim_maxh == 0x7fffffff) {
	limit->rlim_max = RLIM_INFINITY;
	hardok = TRUE;
    }

    if (sizeof(limit->rlim_cur) == 8) {
	if (!softok) {
	    limit->rlim_cur = rlimit->rlim_curh;
	    limit->rlim_cur = limit->rlim_cur << SHIFT_32;
	    limit->rlim_cur |= (rlimit->rlim_curl & 0xffffffff);
	}

	if (!hardok) {
	    limit->rlim_max = rlimit->rlim_maxh;
	    limit->rlim_max = limit->rlim_max << SHIFT_32;
	    limit->rlim_max |= (rlimit->rlim_maxl & 0xffffffff);
	}
    } else {
	if (!softok) {
	    if ((rlimit->rlim_curh > 0) || (rlimit->rlim_curl & 0x80000000))
		limit->rlim_cur = RLIM_INFINITY;
	    else
		limit->rlim_cur = rlimit->rlim_curl;
	}

	if (!hardok) {
	    if ((rlimit->rlim_maxh > 0) || (rlimit->rlim_maxl & 0x80000000))
		limit->rlim_max = RLIM_INFINITY;
	    else
		limit->rlim_max = rlimit->rlim_maxl;
	}
    }

#if defined (RLIMIT_NOFILE) || defined (RLIMIT_OPEN_MAX)
    if (index == RESOURCE_LIMIT_NOFILE || index == RESOURCE_LIMIT_OPEN_MAX) {
	unsigned int sys_max = sysconf(_SC_OPEN_MAX);
	if (limit->rlim_cur > sys_max)
	    limit->rlim_cur = sys_max;
	if (limit->rlim_max > sys_max)
	    limit->rlim_max = sys_max;
    }
#endif

    return;
}
